package com.redsoft.spirit.dao;

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.transform.Transformers;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.util.Assert;

/**
 * DAO的封装类.
 * 
 * <pre>
 * 封装一些涉及到原生sql的增删改查分页等功能
 * </pre>
 * 
 * @author 杨雷
 * @since 1.0
 */
public class BaseRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements BaseRepository<T, ID> {

    //父类没有不带参数的构造方法，这里手动构造父类
    public BaseRepositoryImpl(Class<T> domainClass, EntityManager entityManager) {
        super(domainClass, entityManager);
        System.out.println("构造函数" + domainClass);
        this.entityManager = entityManager;
        this.entityClass = domainClass;
    }
    
	@PersistenceContext
	private EntityManager entityManager;
	
	private Class<T> entityClass;

	/**
	 * 查询分页的方法
	 * 
	 * <pre>
	 * 	带着条件进行动态拼接sql的查询方法
	 * </pre>
	 */
	@Override
	public HashMap<String, Object> sqlQuery(String queryString, String countSql, Map<String, ?> values, int offset,
			int limit, String countName, String rowsName) {

		Assert.hasText(queryString, "queryString不能为空");

		HashMap<String, Object> map = new HashMap<String, Object>();

		Query query = entityManager.createNativeQuery(queryString);
		Query countQuery = entityManager.createNativeQuery(countSql);
		
		//给条件赋上值
		if (values != null && !values.isEmpty()) {
			for (Map.Entry<String, ?> entry : values.entrySet()) {  
			    query.setParameter(entry.getKey(), entry.getValue());
				countQuery.setParameter(entry.getKey(), entry.getValue());	  
			} 
		}

		query.setFirstResult(offset);
		query.setMaxResults(limit);
	    query.unwrap(SQLQuery.class).setResultTransformer(new BeanTransformerAdapter(this.entityClass));
		
		Object results = query.getResultList();
		Object resultsCount = countQuery.getSingleResult();

		map.put(countName, resultsCount);
		map.put(rowsName, results);

		return map;
	}

	@Override
	public List sqlQuery(String queryString, Map<String, ?> values) {
		Session session = entityManager.unwrap(org.hibernate.Session.class);
		SQLQuery query = session.createSQLQuery(queryString);
		
//		//给条件赋上值
//		if (values != null && !values.isEmpty()) {
//			for (Map.Entry<String, ?> entry : values.entrySet()) {  
//			    query.setParameter(entry.getKey(), entry.getValue());
//			} 
//		}
		
	    if (values != null) {
	        query.setProperties(values);
	      }
	    query.setResultTransformer(new BeanTransformerAdapter(this.entityClass));
		return query.list();
	}

	@Override
	public List sqlQuery(String queryString, Object... values) {
		Query query = entityManager.createNativeQuery(queryString);
//		Session session = entityManager.unwrap(org.hibernate.Session.class);
//		SQLQuery query = session.createSQLQuery(queryString);

	    if (values != null) {
	        for (int i = 0; i < values.length; i++) {
	          query.setParameter(i + 1, values[i]);
	        }
	      }
	    query.unwrap(SQLQuery.class).setResultTransformer(new BeanTransformerAdapter(this.entityClass));
		
		return query.getResultList();
	}

	@Override
	public HashMap<String, Object> retrieve(String queryString, String countHql, Map<String, ?> values, int offset,
			int limit, String countName, String rowsName) {

		HashMap<String, Object> map = new HashMap<String, Object>();

		Query query = entityManager.createQuery(queryString);
		Query countQuery = entityManager.createQuery(countHql);
		
		//给条件赋上值
		if (values != null && !values.isEmpty()) {
			for (Map.Entry<String, ?> entry : values.entrySet()) {  
			    query.setParameter(entry.getKey(), entry.getValue());
				countQuery.setParameter(entry.getKey(), entry.getValue());	  
			} 
		}
		query.setFirstResult(offset);
		query.setMaxResults(limit);
		
		Object results = query.getResultList();
		Object resultsCount = countQuery.getSingleResult();

		map.put(countName, resultsCount);
		map.put(rowsName, results);

		return map;
	}

	@Override
	public List<Object> sqlQueryNotFormat(String queryString, Map<String, ?> values) {

		Session session = entityManager.unwrap(org.hibernate.Session.class);
		SQLQuery query = session.createSQLQuery(queryString);

	    if (values != null) {
	        query.setProperties(values);
	      }
//	    query.setResultTransformer(new BeanTransformerAdapter(this.entityClass));
		
		return query.list();
	}

	@Override
	public List<Object> sqlQueryNotFormat(String queryString, Object... values) {
		Query query = entityManager.createNativeQuery(queryString);
		
	    if (values != null) {
	        for (int i = 0; i < values.length; i++) {
	          query.setParameter(i + 1, values[i]);
	        }
	      }
//	    query.unwrap(SQLQuery.class).setResultTransformer(new BeanTransformerAdapter(this.entityClass));
		
		return query.getResultList();
	}
	
	@Override
	public List sqlQueryMap(String queryString, Object... values) {
		Query query = entityManager.createNativeQuery(queryString);
		
	    if (values != null) {
	        for (int i = 0; i < values.length; i++) {
	          query.setParameter(i + 1, values[i]);
	        }
	      }

	    query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
	    
		return query.getResultList();
	}
	
	@Override
	public List sqlQueryMap(String queryString, Map<String, ?> values) {

		Session session = entityManager.unwrap(org.hibernate.Session.class);
		SQLQuery query = session.createSQLQuery(queryString);

	    if (values != null) {
	        query.setProperties(values);
	      }
	    query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
	    
		return query.list();
	}
}
